package com.tal.pad;

import com.google.gson.Gson;
import com.sun.jna.NativeLibrary;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.Word;
import org.bytedeco.opencv.opencv_core.Rect;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
import java.util.function.Consumer;

import static net.sourceforge.tess4j.ITessAPI.TessOcrEngineMode.OEM_DEFAULT;
import static net.sourceforge.tess4j.ITessAPI.TessPageIteratorLevel.RIL_WORD;

public class DingTest_Tesseract {

    private static final String  main_class = "com.tal100.yach/com.tal100.yach.main.activity.MainTabActivity";

    /**
     * 24小时循环一次
     */
    private static final long period = 1000 * 3600 * 24L;

    static DingConfig config;
    private static File properties;

    static{
        /// 读取配置
        try {
            readConfig();
        } catch (IOException e) {
            System.out.println("read config :- error  " + DingTest_Tesseract.config +" progress abort -1  e: "+e.getMessage());
            Runtime.getRuntime().exit(-1);
        }
    }

//    adb shell dumpsys window windows|grep "WorkPlatformActivity" 是否处于工作台

    public static void main(String[] args) throws IOException, InterruptedException {
        String cmd = null;
         if(args.length>0) {
             cmd = args[0];
         }
         System.out.println("read-command: "+ cmd + "properties.getParentFile().getAbsolutePath() "+properties.getParentFile().getAbsolutePath());

//         execcmd(buildcmd("exec-out","screencap","-p >","screenshot.png"),false);
//        adb shell screencap -p

         execcmd(buildcmd("shell","screencap","-p > /sdcard/screenshot.png"),true);
         execcmd(buildcmd("pull","/sdcard/screenshot.png","."),false);

        Arrays.stream(Objects.requireNonNull(properties.getParentFile().listFiles((dir, name) -> name.toLowerCase().contains("screenshot.png")))).forEach(new Consumer<File>() {

            @Override
            public void accept(File file) {
                System.out.println(file.getName() + " filePath : "+ file.getAbsolutePath());
                ocrTxtPos(file);
            }
        });


//
//        if(cmd!=null && !cmd.isEmpty()){
//            execDing(cmd);
//        }else{
//            /// 定时执行
//            autoExecByTimer();
//        }
    }

    private static void ocrTxtPos(File file) {
        NativeLibrary.addSearchPath("tesseract","/opt/homebrew/Cellar/tesseract/5.5.0/lib");
        ITesseract tesseract = new Tesseract();
        tesseract.setDatapath("/opt/homebrew/Cellar/tesseract/5.5.0/share/tessdata");
//        tesseract.setOcrEngineMode(OEM_TESSERACT_ONLY);
        tesseract.setOcrEngineMode(OEM_DEFAULT);
//        tesseract.setOcrEngineMode(OEM_TESSERACT_LSTM_COMBINED);
        tesseract.setLanguage("chi_sim");
//        tesseract.setLanguage("chi_sim+eng");
        tesseract.setTessVariable("user_words_suffix","/opt/homebrew/Cellar/tesseract/5.5.0/share/tessdata/chi_sim_userwords.txt");
//        tesseract.setDatapath("/opt/homebrew/Cellar/tesseract/5.5.0/share/tessdata/chi_sim.traineddata");

        try {

            BufferedImage   originalImage=   ImageIO.read(file);


//            int width = originalImage.getWidth();
//            int height = originalImage.getHeight();
//
//            AffineTransform affineTransform = new AffineTransform();
//            // 绕图片中心向右旋转180度，顺时针方向，角度为 Math.PI
//            affineTransform.rotate(Math.PI/2, width / 2, height / 2);
//
//            AffineTransformOp affineTransformOp = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
//            BufferedImage rotatedImage = affineTransformOp.filter(originalImage, null);
//
//            File outputFile = new File("output.jpg");
//            ImageIO.write(rotatedImage, "jpg", outputFile);

//            String s = tesseract.doOCR(originalImage);
//            System.out.println("s: " + s);

            List<Word> words = tesseract.getWords(originalImage, RIL_WORD);

            for (Word word : words) {
                System.out.println("单词: " + word.getText());
                System.out.println("坐标: " + word.getBoundingBox().toString());
            }

            BufferedImage image = ImageIO.read(file);
            Graphics2D g2d = image.createGraphics();
            g2d.setColor(Color.RED);
            g2d.setStroke(new BasicStroke(2));

            for (Word word : words) {
                Rectangle boundingBox = word.getBoundingBox();
                g2d.drawRect(boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height);
            }
            g2d.dispose();

            // 保存绘制好框的图片
            File outputFile = new File(properties.getParentFile().getAbsolutePath(),  System.currentTimeMillis()+"_rect.jpg");
            System.out.println("outputFile : " + outputFile.getAbsolutePath());
            ImageIO.write(image, "jpg", outputFile);

        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void autoExecByTimer() {
        Timer timer = new Timer();
        Calendar temp = Calendar.getInstance(TimeZone.getDefault());

        int i = temp.get(Calendar.HOUR_OF_DAY);
        int d =  temp.get(Calendar.DAY_OF_MONTH);
        int upDay =d;
        int downDay =d;
        if(i>0&&i<9){
            upDay = d;
            downDay = d;
        }else if(i>=9 &&i<config.getDown_time()[0]+1){ // 上班已过去 设置下一天
            downDay = d;
            temp.add(Calendar.DAY_OF_MONTH,1);
            upDay = temp.get(Calendar.DAY_OF_MONTH);
        }else {  // 下一天的时间
            temp.add(Calendar.DAY_OF_MONTH,1);
            downDay= upDay = temp.get(Calendar.DAY_OF_MONTH);
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Calendar upDate = Calendar.getInstance(TimeZone.getDefault());
        upDate.set(Calendar.DAY_OF_MONTH,upDay);
        upDate.set(Calendar.HOUR_OF_DAY, config.getUp_time()[0]);
        upDate.set(Calendar.MINUTE, config.getUp_time()[1]);
        upDate.set(Calendar.SECOND,new Random().nextInt(60));
        upDate.set(Calendar.MILLISECOND,new Random().nextInt(60));
        timer.scheduleAtFixedRate(new DingTask("up"),new Date(upDate.getTimeInMillis()),period);

        Calendar downDate = Calendar.getInstance(TimeZone.getDefault());
        downDate.set(Calendar.DAY_OF_MONTH,downDay);
        downDate.set(Calendar.HOUR_OF_DAY, config.getDown_time()[0]);
        downDate.set(Calendar.MINUTE, config.getDown_time()[1]);
        downDate.set(Calendar.SECOND,new Random().nextInt(60));
        downDate.set(Calendar.MILLISECOND,new Random().nextInt(60));
        timer.scheduleAtFixedRate(new DingTask("down"),new Date(downDate.getTimeInMillis()),period);
        System.out.println("upDate: "+  sdf.format(new Date(upDate.getTimeInMillis())) + " downDate: "+ sdf.format(new Date(downDate.getTimeInMillis())));
    }

    private static void execDing(String cmd) throws IOException, InterruptedException {
        /// list 设备
        execcmd(buildcmd("devices"),false);

//        adb shell "dumpsys display|grep mScreenState"  mScreenState=ON  mScreenState=OFF
        if(execcmd(buildcmd("shell", "dumpsys", "display|grep", "mScreenState"), false).contains("=OFF")){
            //      解锁屏幕
            lockscreenOn();
        }
////         启动主页面
        execcmd(buildcmd("shell ","am", "start",  main_class),true);

//        adb shell dumpsys window|grep "ActivityRecord"|grep "WorkPlatformActivity"
//        execcmd(buildcmd("shell","dumpsys", "window", "windows|grep" ,"\"ActivityRecord\"|grep", "\"WorkPlatformActivity\""),false);

//        // adb shell input tap 915 2462    消息
        execcmd(buildcmd("shell ","input", "tap", ""+ config.getMsg_tab()[0],""+ config.getMsg_tab()[1]),true);
//
////        adb shell input tap 915 2462    工作台
        execcmd(buildcmd("shell ","input", "tap", ""+ config.getMain_tab()[0],""+ config.getMain_tab()[1]),true);

        if(Objects.equals(cmd, "up")){
            execmdUp();
        } else if (Objects.equals(cmd,"down")) {
            execcmdDown();
        }

        /// 锁屏
        lockscreen();
    }


    private static void readConfig() throws IOException {
         properties = new File(System.getProperty("user.dir"), "pos.properties");
         System.out.println("properties : " + properties.getAbsolutePath() );
//        String string = new PosConfig().toString();
//        System.out.println("posconfig : " + string);

        try (InputStream config = new FileInputStream(properties)) {
            InputStreamReader inputStreamReader = new InputStreamReader(config);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            StringBuilder sb = new StringBuilder();
            String line;
            //直到读完为止
            while((line=bufferedReader.readLine())!=null) {
                sb.append(line);
            }
            DingTest_Tesseract.config = new Gson().fromJson(sb.toString(), DingConfig.class);
            System.out.println("read config :-" + DingTest_Tesseract.config);

            /// setting adb  path
            if(DingTest_Tesseract.config.getExe_path()!=null && new File(DingTest_Tesseract.config.getExe_path()).exists()) {
                System.out.println("adbExeFile : " + DingTest_Tesseract.config.getExe_path());
            }else{
                File adbExeFile = new File(properties.getParentFile(), "adb");
                System.out.println("adbExeFile : " + adbExeFile.getAbsolutePath() );
                if(adbExeFile.exists()&& adbExeFile.canExecute()){
                    DingTest_Tesseract.config.setExe_path(adbExeFile.getAbsolutePath());
                    System.out.println("read config :-" + DingTest_Tesseract.config);
                }else{
                    System.out.println("read config :- error  " + DingTest_Tesseract.config +" progress abort -1");
                    Runtime.getRuntime().exit(-1);
                }
            }
        }
    }


    private static void execmdUp() throws IOException, InterruptedException {
        // 上班打卡自动
////        adb shell input tap 230 1137
        execcmd(buildcmd("shell ","input", "tap", ""+ config.getKq_btn_pos()[0],""+ config.getKq_btn_pos()[1]),true);

        ///上班打卡
        execcmd(buildcmd("shell ","input", "tap", ""+ config.getKq_btn_up_pos()[0],""+ config.getKq_btn_up_pos()[1]),true);

        /// 确认按钮
        confirm();

        /// 返回
        execcmd(buildcmd("shell ","input", "keyevent", "4"),true);
    }


    private static void execcmdDown() throws IOException, InterruptedException {

        ////        adb shell input tap 230 1137
        execcmd(buildcmd("shell ","input", "tap", ""+ config.getKq_btn_pos()[0],""+ config.getKq_btn_pos()[1]),true);

        ///打下班卡
        execcmd(buildcmd("shell ","input", "tap", ""+ config.getKq_btn_free_pos()[0],""+ config.getKq_btn_free_pos()[1]),true);

        /// 更新更新下班卡
        execcmd(buildcmd("shell ","input", "tap", ""+ config.getKq_btn_update_free_pos()[0],""+ config.getKq_btn_update_free_pos()[1]),true);

        /// 确认按钮
        confirm();
        /// 二次确认按钮
        confirm();
        /// 返回
        execcmd(buildcmd("shell ","input", "keyevent", "4"),true);

    }

    /// 任务结束 锁屏
    public static void lockscreen() throws IOException, InterruptedException {
        /// home
        execcmd(buildcmd("shell ","input", "keyevent", "3"),true);

        /// 锁屏、 解锁
        execcmd(buildcmd("shell ","input", "keyevent", "26"),false);
    }

    /// 任务开始解锁
    public static void lockscreenOn() throws IOException, InterruptedException {
        ///  解锁
        execcmd(buildcmd("shell ","input", "keyevent", "26"),true);
        ///  滑动解锁  延迟300ms
        execcmd(buildcmd("shell ","input", "swipe", ""+ config.getSwip_open_start()[0],""+ config.getSwip_open_start()[1],""+ config.getSwip_open_end()[0],""+ config.getSwip_open_end()[1]),true);
    }

    public static void confirm() throws IOException, InterruptedException {
        /// 更新更新下班卡
        execcmd(buildcmd("shell ","input", "tap", ""+ config.getKq_btn_update_free_pos_ok()[0],""+ config.getKq_btn_update_free_pos_ok()[1]),true);
    }


    public static  String buildcmd( String...  cmd){
        StringBuilder stringBuilder = new StringBuilder(config.getExe_path()).append(" ");
        Arrays.stream(cmd).forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                stringBuilder.append(s).append(" ");
            }
        });
        System.out.println("execmd : " + stringBuilder.toString());
        return stringBuilder.toString();
    }




    public static String execcmd(String cmd , boolean isDelay) throws IOException, InterruptedException {
        //执行命令
        Process p = Runtime.getRuntime().exec(cmd);
        //取得命令结果的输出流
        InputStream fis=p.getInputStream();
        //用一个读输出流类去读
        InputStreamReader isr=new InputStreamReader(fis);
        //用缓冲器读行
        BufferedReader br=new BufferedReader(isr);

        StringBuilder sb = new StringBuilder();
        String line=null;
        //直到读完为止
        while((line=br.readLine())!=null)
        {
            System.out.println(line);
            sb.append(line).append("\n");
        }
        if(isDelay){
            Thread.sleep(1500);
        }
        return sb.toString();
    }


     static class DingTask extends TimerTask {

         private final String cmd;

         public DingTask(String cmd){
            this.cmd = cmd;
        }

        @Override
        public void run() {
            try {
                int delaySeonds = new Random().nextInt(60);
                System.out.println("execcmd : " + cmd + " executeTime: " + new Date().toLocaleString()  + " delaySeonds: " + delaySeonds +" s ");
                Thread.sleep(delaySeonds*1000);
                execDing(cmd);
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    // 用于存储识别出的文字及其坐标的内部类
    static class TextWithCoords {
        private final String text;
        private final Rect rect;

        public TextWithCoords(String text, Rect rect) {
            this.text = text;
            this.rect = rect;
        }

        public String getText() {
            return text;
        }

        public Rect getRect() {
            return rect;
        }
    }
}
